import { useCall, useSimpleMemo, useToggle } from '@/components';
import { forkHandler, mergeState } from '@/utils';
import { Modal } from 'antd';
import React, {
  Children,
  cloneElement,
  createContext,
  forwardRef,
  isValidElement,
  useContext,
  useEffect,
  useImperativeHandle,
  useMemo,
  useRef,
} from 'react';

const warn = () => {
  console.warn(`useModal should use in components of rendering ClickModal.content `);
};
const init = {
  open() { },
  close() { },
  submit() { },
  toggle() { },
  isOpen() { },
  isModal: false,
};
const Ctx = createContext(init);
ClickModal = forwardRef(ClickModal);

/** 用于封装弹框, 给子元素传递onClick以打开 */
function ClickModal(props, ref) {
  const {
    onOk,
    onCancel,
    onToggle,
    visible,
    confirmLoading,
    children = null,
    content = null,
    hideOk = false,
    ...modalProps
  } = props;
  const [open, toggle] = useToggle(visible, onToggle);
  const [loading, toggleLoading] = useToggle();
  const tl = toggleLoading;

  useEffect(() => {
    if (open && loading) toggleLoading();
  }, [open]);

  const listeners = useRef([]).current;
  const $onOk = (...args) => Promise.all(listeners.map((c) => c?.(args) || Promise.resolve()));

  const handleOk = useCall(forkHandler(tl, $onOk, onOk, tl, toggle, true).catch(tl));

  const handleCancel = useCall(forkHandler(onCancel, () => open && toggle(), true));

  const handleOpen = useCall(() => (!open && toggle(), void 0));

  const isOpen = useCall(() => open);

  const submit = useCall(forkHandler(tl, (p) => p, onOk, tl, toggle, true).catch(tl));

  const instance = useRef({
    isModal: true,
    open: handleOpen,
    close: handleCancel,
    submit,
    toggle,
    isOpen,
    onOk(creator) {
      listeners.push(creator);
      return () => {
        listeners.splice(listeners.indexOf(creator), 1);
      };
    },
  }).current;

  useImperativeHandle(ref, () => instance, []);

  const handleChildClick = useCall(forkHandler(children?.props?.onClick, toggle, true));

  return (
    <>
      {/* 如果子元素只有一个元素 */}
      {isValidElement(children) && Children.count(children) === 1
        ? cloneElement(children, { onClick: handleChildClick })
        : children}
      <Modal
        width='max(640px, min(960px, 65vw))'
        {...useSimpleMemo(mergeState(modalProps, hideOk ? { okButtonProps: { style: { display: 'none' } } } : {}))}
        visible={open}
        confirmLoading={loading}
        onOk={handleOk}
        onCancel={handleCancel}
      >
        <Ctx.Provider value={instance} children={content} />
      </Modal>
    </>
  );
}

export function useModal(factory, deps) {
  const ctx = useContext(Ctx);
  if (process.env.NODE_ENV === 'development') {
    useEffect(() => {
      if (ctx === init) warn();
    }, []);
  }
  //  // "target": "https://baodai.fulan.com.cn",
  const proxy = useMemo(() => {
    return new Proxy(ctx, {
      get(target, p, receiver) {
        if (p === 'isModal') return ctx !== init;
        return Reflect.get.apply(this, arguments);
      },
    });
  }, [ctx]);

  return ctx;
}

export default ClickModal;
